package com.workingpub.commons.resource.internal;

import java.io.IOException;
import java.util.Dictionary;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;

import org.osgi.service.cm.Configuration;
import org.osgi.service.cm.ConfigurationAdmin;
import org.osgi.service.cm.ConfigurationEvent;
import org.osgi.service.cm.ConfigurationListener;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.Assert;
import org.springframework.util.StringUtils;

import com.workingpub.commons.resource.CommonConfig;

public class DefaultCommonConfig implements CommonConfig, ConfigurationListener {
	private static final Logger logger = LoggerFactory.getLogger(DefaultCommonConfig.class);

	private static final Properties properties = new Properties();

	public DefaultCommonConfig() {
		logger.debug("Created instance : " + this);
	}

	@Override
	public String getProperty(String key, String defaultValue) {
		if (properties.containsKey(key)) {
			return properties.getProperty(key);
		} else {
			logger.warn("Failed to read the propertiy from configuration, return default value : {}", defaultValue);
			return defaultValue;
		}
	}

	@Override
	public void reload() {
		try {
			Configuration[] commonConfigs = Activator.getInstance().getConfigurations(DEFAULT_PID_FILTER);
			if (null == commonConfigs || commonConfigs.length == 0) {
				return;
			}
			properties.clear();
			for (Configuration entry : commonConfigs) {
				replace(entry);
			}
			logger.info("Success to reload configuration.\n{}", properties);
		} catch (Exception e) {
			logger.warn("Failed to reload configuration : " + e.getMessage(), e);
			Assert.isNull(e, "Failed to reload configuration : " + e.getMessage());
		}
	}

	private void replace(Configuration config) {
		if (null == config) {
			return;
		}
		Dictionary<?, ?> dictionary = config.getProperties();
		if (null == dictionary || dictionary.isEmpty()) {
			return;
		}
		Enumeration<?> enumeration = dictionary.keys();
		while (enumeration.hasMoreElements()) {
			Object key = enumeration.nextElement();
			properties.put(key, dictionary.get(key));
		}
	}

	@Override
	public Map<String, String> getProperties() {
		@SuppressWarnings("unchecked")
		Map<String, String> allProperties = new HashMap<String, String>((Map<String, String>) properties.clone());
		return allProperties;
	}

	@Override
	public void configurationEvent(ConfigurationEvent event) {
		if (StringUtils.hasText(event.getPid()) && event.getPid().startsWith(DEFAULT_PID_PREFIX)) {
			ConfigurationAdmin configAdmin = (ConfigurationAdmin) Activator.getInstance().getBundleContext()
					.getService(event.getReference());
			if (null == configAdmin) {
				return;
			}

			try {
				replace(configAdmin.getConfiguration(event.getPid()));
				logger.info("Success to process configuration event : {}", event.getPid());
			} catch (IOException e) {
				logger.warn("Failed to process configuration event : " + e.getMessage(), e);
			}
		}
	}
}
